import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, Like } from 'typeorm';
import * as crypto from 'crypto'
import axios from 'axios';
import { KzAccountEntity } from './entities/kz-account.entity';
import { KzSiteEntity } from './entities/kz-site.entity'
import { KzHistoryEntity } from "./entities/site-history.entity";
import { CreateAccountDto } from './dto/create-account.dto';
import { UpdateAccountDto } from './dto/update-account.dto';
import { ListAccountDto } from './dto/list-account.dto'
import { UpdateSiteDto } from './dto/update-site.dto'
import { ListSiteDto } from './dto/list-site.dto';
import { ResultData } from 'src/common/utils/result';
import { getDateAfterDays } from 'src/common/utils'
import * as cheerio from 'cheerio';

@Injectable()
export class KzService {
  constructor(
    @InjectRepository(KzAccountEntity) private readonly kzAccountEntityRep: Repository<KzAccountEntity>,
    @InjectRepository(KzSiteEntity) private readonly KzSiteEntityRep: Repository<KzSiteEntity>,
    @InjectRepository(KzHistoryEntity) private readonly KzHistoryEntityRep: Repository<KzHistoryEntity>,
  ) { }

  // 添加快站账号
  async createAccount(user,CreateAccountDto: CreateAccountDto) {
    let has = await this.kzAccountEntityRep.findOne({ where: { account: CreateAccountDto.account, delFlag: '0' } })
    if (!has) {
      let result = await this.kzAccountEntityRep.save({...CreateAccountDto, createBy: user.username})
      return result;
    } else {
      return ResultData.fail(409, '该账号已存在')
    }
  }

  // 修改快站账号信息
  async updateAccount(user, UpdateAccountDto: UpdateAccountDto) {
    let result = await this.kzAccountEntityRep.update(UpdateAccountDto.id, {...UpdateAccountDto, updateBy: user.username})
    return result;
  }

  // 查询所有快站账号信息
  async findAccounts(query: ListAccountDto) {
    const entity = this.kzAccountEntityRep.createQueryBuilder('entity')
    entity.where('entity.delFlag = :delFlag', { delFlag: '0' });
    if (query.account) {
      entity.andWhere(`entity.account LIKE "%${query.account}%"`);
    }

    if (query.params?.beginTime && query.params?.endTime) {
      entity.andWhere('entity.createTime BETWEEN :start AND :end', { start: query.params.beginTime, end: query.params.endTime });
    }

    if (query.pageSize && query.pageNum) {
      entity.skip(query.pageSize * (query.pageNum - 1)).take(query.pageSize);
    }

    const [list, total] = await entity.getManyAndCount();
    return ResultData.ok({
      list,
      total,
    });
  }

  // 同步账号内的所有站点到数据库
  async accountSyncSites(id: number) {
    let kzAccount = await this.kzAccountEntityRep.findOne({ where: { id: id } })

    let sitesRes = await this.reqKzApi({
      url: '/api/v1/tbk/getSiteIds',
      method: 'post'
    }, kzAccount)
    if (sitesRes.code !== 200) {
      return sitesRes
    }
    await this.KzSiteEntityRep.createQueryBuilder('entity').delete().from(KzSiteEntity).where("id = :accountId", { accountId: id })
    let siteIds = sitesRes.data.siteIds || []
    if (siteIds.length) {
      this.kzAccountEntityRep.update(id, { siteCount: siteIds.length })
    }
    for (let id of siteIds) {
      this.getRemoteKzInfo(id, kzAccount)
    }
    return ResultData.ok(sitesRes.data);
  }

  // 站点列表查询
  async findSites(query: ListSiteDto) {
    const entity = this.KzSiteEntityRep.createQueryBuilder('entity')
    entity.where('entity.delFlag = :delFlag', { delFlag: '0' });

    if (query.account) {
      let kzAccount = await this.kzAccountEntityRep.find({ where: { account: Like(`%${query.account}%`), delFlag: '0' } })
      if (kzAccount.length > 0) {
        let kzAccountIds = kzAccount.map(item => item.id)
        entity.andWhere('entity.account in (:...kzAccountIds)', { kzAccountIds: kzAccountIds });
      } else {
        return ResultData.ok({
          list: [],
          total: 0
        });
      }
    }
    if (query.packageName) {
      entity.andWhere(`entity.packageName = :packageName`, { packageName: query.packageName });
    }

    if (query.keyWord) {
      entity.andWhere('entity.siteDomain LIKE :keyWord OR entity.siteId LIKE :keyWord OR entity.siteName LIKE :keyWord', { keyWord: `%${query.keyWord}%` });
    }

    if (query.pageSize && query.pageNum) {
      entity.skip(query.pageSize * (query.pageNum - 1)).take(query.pageSize);
    }

    entity.leftJoin("entity.account", "account").select(['entity']).addSelect(['account.account'])

    const [list, total] = await entity.getManyAndCount();
    return ResultData.ok({
      list,
      total,
    });
  }

  // 更新快站站点
  async updateSite(UpdateSiteDto: UpdateSiteDto) {
    let siteItem = await this.KzSiteEntityRep.findOne({
      where: { siteId: UpdateSiteDto.siteId },
      relations: ["account"]
    })
    let kzAccount = siteItem.account
    // 更新域名
    if (UpdateSiteDto?.siteDomain) {
      const res = await this.reqKzApi({
        url: '/api/v1/tbk/changeDomain',
        method: 'post',
        data: {
          siteId: UpdateSiteDto.siteId,
          domain: UpdateSiteDto.siteDomain
        }
      }, kzAccount)
      if (res.code !== 200) {
        return res
      }
      if (res?.data?.newDomain) {
        let saveDomain = res?.data?.newDomain
        if (saveDomain.indexOf('https://') === -1) {
          saveDomain = 'https://' + saveDomain
        }
        // 记录修改记录
        this.KzHistoryEntityRep.insert({ siteId: UpdateSiteDto.siteId, beforeContent: siteItem.siteDomain, updateContent: saveDomain })
        this.KzSiteEntityRep.update({ siteId: UpdateSiteDto.siteId }, { siteDomain: saveDomain })
      }
      return res
    }

    // 更新页面内容
    if (UpdateSiteDto?.siteContent) {
      // 检查更新内容字段是否是域名
    const domainRegex = /^https?:\/\/([a-zA-Z0-9-]+\.)+([a-zA-Z]{2,})(:[0-9]{1,5})?(\/[a-zA-Z0-9._-]*|\/#)*(\?[a-zA-Z0-9#=&%._-]*)?$/;
    let siteContent = UpdateSiteDto.siteContent
    if(domainRegex.test(UpdateSiteDto.siteContent)) {
      let res = await axios.get(UpdateSiteDto.siteContent, {
        responseType: 'text'
      })
      siteContent = res.data.replace(/^\s+|\s+$/g, '')
    }

    let modifyRes = await this.reqKzApi({
      url: '/api/v1/tbk/modifyPageJs',
      method: 'post',
      data: {
        siteId: UpdateSiteDto.siteId,
        content: siteContent
      }
    }, kzAccount)
    if (modifyRes.code !== 200) {
      return modifyRes
    }
    await this.KzHistoryEntityRep.insert({ siteId: UpdateSiteDto.siteId, beforeContent: UpdateSiteDto.curContent, updateContent: siteContent, updateType: '2' })
    let publishRes = await this.reqKzApi({
      url: '/api/v1/tbk/publishPage',
      method: 'post',
      data: {
        siteId: UpdateSiteDto.siteId,
      }
    }, kzAccount)
    if (publishRes.code !== 200) {
      return ResultData.fail(400, '更新成功但发布失败！')
    }
    return ResultData.ok(publishRes.data, '更新发布成功！')
    }

    // 更新站点名称
    if(UpdateSiteDto?.siteName) {
        const res = await this.reqKzApi({
            url: '/api/v1/tbk/updateSiteSetting',
            method: 'post',
            data: {
                siteId: UpdateSiteDto.siteId,
                siteName: UpdateSiteDto.siteName
            }
        }, kzAccount)
        if (res.code === 200) {
            // 记录修改记录
            this.KzHistoryEntityRep.insert({
                siteId: UpdateSiteDto.siteId,
                beforeContent: siteItem.siteName,
                updateContent: UpdateSiteDto.siteName,
                updateType: '3'
            })
            this.KzSiteEntityRep.update({siteId: UpdateSiteDto.siteId}, {siteName: UpdateSiteDto.siteName})
        }
        return res
    }
  }

  // 查询站点域名页面内容
  async findSiteContent(siteId: string) {
    let siteItem = await this.KzSiteEntityRep.findOne({ where: { siteId }, relations: ["account"] })
    let kzAccount = siteItem.account
    const res = await this.getRemoteKzInfo(siteItem.siteId, kzAccount)
    const contentRes = await this.getKzContent(res.siteDomain)
    return contentRes
  }

  // 检查站点域名是否被微信封禁
  async checkSiteDomainBan(siteId: string, autoUpdate?: boolean) {
    let siteItem = await this.KzSiteEntityRep.findOne({
      where: { siteId: siteId },
      relations: ["account"]
    })
    let kzAccount = siteItem.account
    let domainRes = await this.reqKzApi({
      url: '/api/v1/tbk/getDomain',
      method: 'post',
      data: {
        siteId: siteId
      }
    }, kzAccount)

    if (domainRes.code !== 200) {
      return domainRes
    }
    let res = await this.reqKzApi({
      url: '/api/v1/tbk/checkDomainBan',
      method: 'post',
      data: {
        ...domainRes.data
      }
    }, kzAccount)
    if (res.code !== 200) {
      return res
    }
    // 自动更新域名
    if (res.data.isBannedWX && autoUpdate) {
      let banDomain = domainRes.data.domain
      let regex = /^([^.]+)\..+\..+$/;
      let match = banDomain.match(regex);
      if (match && match[1]) {
        let banDomain = match[1];
        let newDomain = ''
        let numMatch = banDomain.match(/\d+$/);
        if (numMatch) {
          let num = parseInt(numMatch[0]);
          newDomain = banDomain.slice(0, -numMatch[0].length) + (num + 1);
        } else {
          newDomain = banDomain + "001";
        }
        let result = await this.updateSite({siteId: siteId, siteDomain: newDomain})
        if (result.code !== 200) {
          return result
        }
        return ResultData.ok(result.data, '发现快站被封禁，已自动更新')
      }
    } else {
      return res
    }
  }

  // 站点修改历史查询
  async findSiteHistory(query) {
    const entity = this.KzHistoryEntityRep.createQueryBuilder('entity')
    entity.where('entity.siteId = :siteId', { siteId: query.siteId });
    if (query.updateType) {
      entity.andWhere('entity.updateType = :updateType', { updateType: query.updateType });
    }
    entity.orderBy('entity.createTime', 'DESC')
    let pageSize = query.pageSize || 10
    let pageNum = query.pageNum || 1
    entity.skip(pageSize * (pageNum - 1)).take(pageSize);
    const [list, total] = await entity.getManyAndCount();
    return ResultData.ok({
      list,
      total,
    });
  }

  // 同步单个站点到数据库
  async siteSync(user, siteId: string) {
    let siteItem = await this.KzSiteEntityRep.findOne({ where: { siteId }, relations: ["account"] })
    let kzAccount = siteItem.account
    let res = await this.getRemoteKzInfo(siteId, kzAccount)
    return ResultData.ok(res)
  }

  // 获取站点基本信息并存入数据库
  async getRemoteKzInfo(id: number | string, kzAccount: KzAccountEntity) {
    let response = await this.reqKzApi({
      url: '/api/v1/tbk/getSiteInfo',
      method: 'post',
      data: {
        siteId: id
      }
    }, kzAccount)
    if (response.code !== 200) {
      return response
    }

    let siteOne = {
      ...response.data,
      packageExpiryDate: getDateAfterDays(response.data.packageRemainingDays),
      account: kzAccount.id
    }
    let result = await this.KzSiteEntityRep.save(siteOne);

    console.log(result);
    return result
  }

  // 获取站点内容
  async getKzContent(siteUrl: string) {
    let res = await axios.get(siteUrl, {
      responseType: 'text'
    })
    let htmlStr = res.data.replace(/^\s+|\s+$/g, '')
    const startTag = '<div class="mod mod-js">';
    const endTag = '</html>';
    const regex = new RegExp(startTag + '(.*?)' + endTag + '(?!$)', 's');
    const match = htmlStr.match(regex);
    let siteContent = ''
    if (match && match.length > 1) {
      siteContent = match[1] + endTag
    } else {
      // 使用Cheerio加载HTML片段
      const $ = cheerio.load(htmlStr);
      const targetDiv = $('.mod.mod-js');
      const content = targetDiv.html();
      siteContent = content ? content.toString() : '';
    }
    return ResultData.ok(siteContent)
  }


  // 请求快站api
  async reqKzApi(options: any, kzAccount: KzAccountEntity) {
    let appKey = kzAccount.appKey
    let data = {
      ...options.data,
      appKey
    }
    let sign = this.createKzSign(data, kzAccount.appSecret)
    let req = {
      url: options.url,
      method: options.method,
    }
    if (options.method === 'get') {
      (req as any).params = {
        ...data,
        appKey,
      }
    } else {
      (req as any).data = {
        ...data,
        sign
      }
    }
    try {
      const response = await axios.request({
        baseURL: 'https://cloud.kuaizhan.com',
        headers: options.headers || { 'Content-Type': 'application/x-www-form-urlencoded' },
        ...req
      })
      if (response.data.code === 200) {
        return ResultData.ok(response.data.data)
      } else {
        return ResultData.fail(response.data.code, response.data.msg)
      }
    } catch (error) {
      return ResultData.fail(error.response.data.code, error.response.data.msg)
    }
  }

  // 生成请求快站api签名
  createKzSign(params: Object, appSecret?: string) {
    const sortedParams = Object.keys(params).sort().map(key => `${key}${params[key]}`);
    const paramsStr = sortedParams.join('');
    const signStr = appSecret + paramsStr + appSecret
    // Object.keys(params)
    //   .sort()
    //   .map(item => {
    //     paramsStr += item + params[item]
    //   })
    //   let kzSign = md5Hash.update(appSecret + paramsStr + appSecret).digest('hex');
    const md5Hash = crypto.createHash('md5');
    md5Hash.update(signStr, 'utf-8')
    return md5Hash.digest('hex')
  }
}
